package divide;

/**
 * Class that describe the logic of column dividing.
 *
 * @author Muzalevskiy Vitaliy
 */
public class ColumnDivider {

    /**
     * This class include all results of column division process that we need
     * to build result of division in form of column.
     */
    public class DividingResult {

        /**
         * Dividend value.
         */
        private int dividend;
        /**
         * Divisor value.
         */
        private int divisor;
        /**
         * Value of division result.
         */
        private int result;
        /**
         * Value of rest after division.
         */
        private int rest;
        /**
         * Intermediate value of division process.
         */
        private int intermidiateValue;
        /**
         * Max value of array that include intermediate values length.
         */
        public final static int ARRAY_LENGTH = 20;
        /**
         * Array of intermediate dividend values.
         */
        private int[] dividentIntermidiateArray = new int[ARRAY_LENGTH];
        /**
         * Array of intermediate values.
         */
        private int[] intermidiateValueArray = new int[ARRAY_LENGTH];
        /**
         * This value gather by symbols value of result.
         */
        private StringBuilder resultBuilder = new StringBuilder();
        /**
         * This value gather by symbols intermediate value of division.
         */
        private StringBuilder intermidiateValueBuilder = new StringBuilder();
        /**
         * Counter of values gathered in array.
         */
        private int arrayCount;

        /**
         * Constructor of <code> DividingResult </code>. As parameters it get
         * the values of dividend and divisor.
         * 
         * @param dividend
         * @param divisor 
         */
        private DividingResult(int dividend, int divisor) {
            this.dividend = dividend;
            this.divisor = divisor;
        }

        /**
         * @return the dividend
         */
        public int getDividend() {
            return dividend;
        }

        /**
         * @return the divisor
         */
        public int getDivisor() {
            return divisor;
        }

        /**
         * @return the result
         */
        public int getResult() {
            return result;
        }

        /**
         * @return the rest
         */
        public int getRest() {
            return rest;
        }

        /**
         * @return the intermidiateValue
         */
        public int getIntermidiateValue() {
            return intermidiateValue;
        }

        /**
         * @return the dividentIntermidiateArray
         */
        public int[] getDividentIntermidiateArray() {
            return dividentIntermidiateArray;
        }

        /**
         * @return the intermidiateValueArray
         */
        public int[] getIntermidiateValueArray() {
            return intermidiateValueArray;
        }

        /**
         * @return the resultBuilder
         */
        public StringBuilder getResultBuilder() {
            return resultBuilder;
        }

        /**
         * @return the intermidiateValueBuilder
         */
        public StringBuilder getIntermidiateValueBuilder() {
            return intermidiateValueBuilder;
        }
    }

    /**
     * This method realized division of two numbers that it gat as parameters
     * and return <code> DividingResult </code> type value that include all
     * parameters needed for column forming.
     *
     * @param dividend - dividend value.
     * @param divisor - divisor value.
     * @return <code> DividingResult </code> value that can use for future 
     *      processing.
     * @throws IllegalArgumentException if value of divisor equals 0.
     */
    public DividingResult divide(int dividend, int divisor) {
        if(divisor == 0){
            throw new IllegalArgumentException();
        }
        DividingResult dividingResult = new DividingResult(dividend, divisor);
        dividingResult.arrayCount = 0;
        dividingHandler(dividingResult);
        formResultValue(dividingResult);
        dividingResult.rest = Integer.valueOf(dividingResult
                .getIntermidiateValueBuilder().toString());
        return dividingResult;
    }   

    private void dividingHandler(DividingResult dividingResult) {
        for (int count = 0; count < String.valueOf(dividingResult.dividend).length(); count++) {
            dividingResult.getIntermidiateValueBuilder()
                    .append(String.valueOf(getNumber(dividingResult.dividend, count)));
            dividingResult.intermidiateValue = Integer.valueOf(dividingResult
                    .getIntermidiateValueBuilder().toString());
            buildResult(dividingResult);
        }
    }

    private int getNumber(int value, int count) {
        String valueToString = String.valueOf(value);
        int number = Integer.valueOf(String.valueOf(valueToString.charAt(count)));
        return number;
    }
    
    private void formResultValue(DividingResult dividingResult){
        try {
            dividingResult.result = Integer.valueOf(dividingResult
                    .getResultBuilder().toString());
        } catch (NumberFormatException e) {
            dividingResult.result = 0;
        }
    }
    
    private void buildResult(DividingResult dividingResult) {
        if (dividingResult.getIntermidiateValue() >= dividingResult.divisor) {
            dividingResult.getResultBuilder().append(dividingResult
                    .getIntermidiateValue() / dividingResult.divisor);
            dividingResult.intermidiateValueBuilder = new StringBuilder(
                    String.valueOf(dividingResult
                    .getIntermidiateValue() % dividingResult.divisor));
            dividingResult.dividentIntermidiateArray[dividingResult.arrayCount] =
                    dividingResult.getIntermidiateValue();
            dividingResult.intermidiateValueArray[dividingResult.arrayCount] =
                    (dividingResult.getIntermidiateValue() / dividingResult.divisor) 
                    * dividingResult.divisor;
            dividingResult.arrayCount++;
        } else {
            dividingResult.getResultBuilder().append(String.valueOf(0));
        }
    }
}
